package vcd_loader

class DeqInfo(i:Int,signals:Map[String,VSignal]){
    val sig_btype  = signals(s"brq_1_io_to_fe_deq_backup_${i}_btype")
    val sig_hit    = signals(s"brq_1_io_to_fe_deq_save_${i}_ftb_sav_hit")
    val sig_last   = signals(s"brq_1_io_to_fe_deq_save_${i}_last")
    val sig_error  = signals(s"brq_1_io_to_fe_deq_save_${i}_error")
    val sig_pc_nt  = signals(s"brq_1_io_to_fe_deq_pc_nt_${i}")
    val sig_target = signals(s"brq_1_io_to_fe_deq_target_${i}")
    def btype     = sig_btype.last
    def hit       = sig_hit.last.testBit(0)
    def pc_nt     = sig_pc_nt.last.toLong
    def target    = sig_target.last.toLong
    def last      = sig_last.last.testBit(0)
    def error     = sig_error.last.testBit(0)
}

object VCDLoaderMain{
    def main(args:Array[String]){
        import scala.collection.mutable
        val vcd = new VCDLoader("data/test.vcd")
        val br_trace = new java.io.PrintWriter("data/br-trace.txt")
        val top = vcd.top.getScope("Top")
        val deq_signals = top.signals.filter(kv=>kv._1.startsWith("brq_1_io_to_fe_deq"))
        val deq_valid   = top.signals("brq_1_io_to_fe_deq_req")
        val deq_error   = top.signals("brq_1_io_to_fe_deq_error")
        val deq_taken   = top.signals("brq_1_io_to_fe_deq_taken")
        val deq = Array.tabulate(6)(i=>new DeqInfo(i,deq_signals))
        var blk_count = 0
        var blk_error = 0
        var branch_count = 0
        var branch_error_miss = 0
        var branch_error_hit  = 0
        def branch_error  = branch_error_hit + branch_error_miss
        var br_count_hit  = 0
        var br_count_miss = 0
        def br_count      = br_count_hit + br_count_miss
        var br_error_hit  = 0
        var br_error_miss = 0
        def br_error      = br_error_hit + br_error_miss
        var pc_start = 0x1c000000L
        vcd.sim(t=>{
            var i = 0
            while(deq_valid.last.testBit(i)){
                if(deq(i).last)
                    blk_count += 1
                if(deq(i).error){
                    blk_error += 1
                }
                if(deq_error.last.testBit(i)){
                    if(deq(i).hit && deq(i).last)
                        branch_error_hit += 1
                    else
                        branch_error_miss += 1
                }
                var br_pred = 0
                val taken = if(deq_taken.last.testBit(i)) 1 else 0
                if(deq(i).btype.testBit(1)){
                    branch_count += 1
                }
                else if(deq(i).btype.testBit(0)){
                    branch_count += 1
                    if(deq_error.last.testBit(i)){
                        if(deq(i).hit && deq(i).last){
                            br_error_hit += 1
                        }
                        else
                            br_error_miss += 1
                    }
                    if(deq(i).hit && deq(i).last){
                        br_pred = 1
                        br_count_hit += 1
                    }
                    else{
                        br_count_miss += 1
                    }
                }
                if(taken != 0 || br_pred != 0){
                   br_trace.write(s"${pc_start.toHexString} ${deq(i).pc_nt.toHexString} ${deq(i).target.toHexString} ${taken} ${br_pred}\n")
                }
                if(deq(i).last || deq_error.last.testBit(i)){
                    if(deq_taken.last.testBit(i)){
                        pc_start = deq(i).target
                    }
                    else{
                        pc_start = deq(i).pc_nt
                    }
                }
                i += 1
            }
        })
        br_trace.close()
        println(s"""|blk_count:$blk_count
                    |blk_error:$blk_error
                    |branch_count:$branch_count
                    |branch_error_hit:$branch_error_hit
                    |branch_error_miss:$branch_error_miss
                    |branch_error:$branch_error
                    |br_count:$br_count
                    |br_count_hit:$br_count_hit
                    |br_count_miss:$br_count_miss
                    |br_error:$br_error
                    |br_error_hit:$br_error_hit
                    |br_error_miss:$br_error_miss
                    |""".stripMargin)
    }
};
